#ifndef KU6_BLOCK_QUEUE_H
#define KU6_BLOCK_QUEUE_H 1

#include <pthread.h>
#include <stddef.h> 

typedef void (*free_func)(void *);

typedef struct queue_t {
    struct queue_t *prev;
    struct queue_t *next;
} queue_t;

typedef struct block_queue_t {
    queue_t queue;
    int size; 
    int max_size;
    unsigned short block_flag:1;
    pthread_mutex_t mutex;
    pthread_cond_t  cond;
} block_queue_t;

#define queue_init(q)           \
	(q)->prev = q;              \
	(q)->next = q

#define queue_empty(h)          \
	(h == (h)->prev)

#define queue_insert_head(h,x)	\
        (x)->next = (h)->next;	\
        (x)->next->prev = x;  	\
        (x)->prev = h;		    \
        (h)->next = x

#define queue_insert_after   queue_insert_head

#define queue_insert_tail(h, x)     \
    (x)->prev = (h)->prev;          \
    (x)->prev->next = x;            \
    (x)->next = h;                  \
    (h)->prev = x

#define queue_head(h)               \
    (h)->next

#define queue_last(h)               \
    (h)->prev

#define queue_sentinel(h)           \
    (h)

#define queue_next(q)               \
    (q)->next

#define queue_prev(q)               \
    (q)->prev

#if (NGX_DEBUG)

#define queue_remove(x)             \
    (x)->next->prev = (x)->prev;    \
    (x)->prev->next = (x)->next;    \
    (x)->prev = NULL;               \
    (x)->next = NULL

#else

#define queue_remove(x)             \
    (x)->next->prev = (x)->prev;    \
    (x)->prev->next = (x)->next

#endif

#define queue_split(h, q, n)        \
    (n)->prev = (h)->prev;          \
    (n)->prev->next = n;            \
    (n)->next = q;                  \
    (h)->prev = (q)->prev;          \
    (h)->prev->next = h;            \
    (q)->prev = n;

#define queue_add(h, n)             \
    (h)->prev->next = (n)->next;    \
    (n)->next->prev = (h)->prev;    \
    (h)->prev = (n)->prev;          \
    (h)->prev->next = h;

#define queue_data(q, type, link)   \
    (type *) ((u_char *) q - offsetof(type, link))

#ifdef  __cplusplus
extern "C" {
#endif

queue_t * queue_middle(queue_t *queue);
int       queue_size(queue_t *q);
void      queue_sort(queue_t *queue, int (*cmp)(const queue_t *, const queue_t *));
void      queue_destory(queue_t *q,free_func func);

void 	  block_queue_destory(block_queue_t *bq,free_func func);
void      block_queue_init(block_queue_t *bq,int max_size,unsigned short block_flag);
int       block_queue_push(block_queue_t *bq,queue_t *entity);
queue_t * block_queue_pop(block_queue_t *bq);
void      broadcast_threads_wakeup(block_queue_t *bq,unsigned short block_flag);

#ifdef  __cplusplus
}
#endif
#endif //KU6_BLOCK_QUEUE_H
